package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.domain.vo.CommentVo;
import com.itheima.domain.vo.MovementVo;
import com.itheima.domain.vo.PageBeanVo;
import com.itheima.domain.vo.UserCommentVo;
import com.itheima.service.db.AnnouncementService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.DateFormatUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class MovementManager {

    @Autowired
    private OssTemplate ossTemplate;

    @Reference
    private MovementService movementService;


    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    //发布动态
    public void saveMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        //1.获取登录用户的id
        Long userId = UserHolder.get().getId();
        //2.图片上传到阿里云，得到返回地址的集合
        ArrayList<String> imageList = new ArrayList<>();
        if (imageContent != null && imageContent.length > 0) {//非空校验
            for (MultipartFile image : imageContent) {
                String imagePath = ossTemplate.upload(image.getOriginalFilename(), image.getInputStream());
                imageList.add("https://"+imagePath);
            }
        }
        //3.封装到一个Movement对象
        movement.setUserId(userId);//用户id
        //movement.setPid(0l);//// TODO: 2021/7/6  临时写死
        movement.setMedias(imageList);//图片列表
        movement.setState(0);
        movement.setCreated(System.currentTimeMillis());//创建时间
        movement.setSeeType(1);//本项目未使用

        //4.调用service保存
        ObjectId movementId = movementService.saveMovement(movement);
        //5.通知华为云审核 传递了动态的id    null.方法
        rocketMQTemplate.convertAndSend("tanhua-huawei",movementId.toHexString());
        //发送MQ操作
        mqMovementManager.sendMessage(movementId.toHexString(), MQMovementManager.MOVEMENT_PUBLISH);
    }

    @Reference
    private UserInfoService userInfoService;

    //查询我的个人动态或者以后查询别人的动态
    public PageBeanVo findMyMovement(Integer pageNumber, Integer pageSize, Long userId) {
        //1.查询个人的动态信息
        PageBeanVo pageBeanVo = movementService.findMyMovement(pageNumber, pageSize, userId);
        //System.out.println(pageBeanVo);


        //2.根据所得到的动态，需要查询到个人的信息
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //定义返回的数据集合
        List<MovementVo> movementVos = new ArrayList<>();

            if (CollectionUtil.isNotEmpty(items)) {
                for (Movement movement : items) {//遍历集合
                    Long movementUserId = movement.getUserId();//发布动态这个人的id
                    UserInfo userInfo = userInfoService.findById(movementUserId);//查询个人的信息

                    //3.将动态和个人的信息封装到一个新的vo对象
                    MovementVo movementVo = new MovementVo();
                    //数据的转换 个人-> vo
                    movementVo.setUserInfo(userInfo);
                    //数据的转换 动态-> vo
                    movementVo.setMovement(movement);
                    String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movement.getId());
                    String key3 = StrUtil.format(ConstantUtil.MOVEMENT_LOVE , UserHolder.getId(),movement.getId());
                    if (stringRedisTemplate.hasKey(key)) {
                        movementVo.setHasLiked(1);//1表示已经点过赞
                    }
                    if (stringRedisTemplate.hasKey(key3)) {
                        movementVo.setHasLoved(1);//1表示已经喜欢
                    }
                    //将封装好的数据   给到集合
                    movementVos.add(movementVo);
                }
        }

        //4.将数据返回
        pageBeanVo.setItems(movementVos);
        //System.out.println("----manager"+pageBeanVo);
        return pageBeanVo;
    }

    /**
     * 查询好友动态
     * @param pageNumber
     * @param pageSize
     * @return
     */
    public PageBeanVo findFriendMovements(Integer pageNumber, Integer pageSize) {
        //1.分页查询个人的动态信息
        PageBeanVo pageBeanVo = movementService.findFriendMovements(pageNumber, pageSize, UserHolder.getId());
        //System.out.println(pageBeanVo);
        //2.根据所得到的的动态，需要查询到个人的信息
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //定义返回的数据集合
        List<MovementVo> movementVos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(items)) {
            for (Movement movement : items) {//遍历动态
                Long userId = movement.getUserId();//发布动态这个人的id
                UserInfo userInfo = userInfoService.findById(userId);//查询个人信息
                //3.将动态和个人信息封装一个新的vo对象
                MovementVo movementVo = new MovementVo();
                //数据的转换  个人-》vo
                movementVo.setUserInfo(userInfo);
                //数据的转换  动态-》vo
                movementVo.setMovement(movement);

                String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movement.getId());
                String key3 = StrUtil.format(ConstantUtil.MOVEMENT_LOVE , UserHolder.getId(),movement.getId());
                if (stringRedisTemplate.hasKey(key)) {
                    movementVo.setHasLiked(1);//1表示已经点过赞
                }
                if (stringRedisTemplate.hasKey(key3)) {
                    movementVo.setHasLoved(1);//1表示已经喜欢
                }
                //将封装好的数据   给到集合
                movementVos.add(movementVo);

            }
        }
        //4.将数据返回
        pageBeanVo.setItems(movementVos);
        return pageBeanVo;
    }




/*
    //查询我的个人动态或者以后查询别人的动态
    public PageBeanVo findMyMovement(Integer pageNumber, Integer pageSize, Long userId) {
        //1.查询个人的动态信息
        PageBeanVo pageBeanVo = movementService.findMyMovement(pageNumber, pageSize, userId);
        //System.out.println(pageBeanVo);


        //2.根据所得到的动态，需要查询到个人的信息
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //定义返回的数据集合
        List<MovementVo> movementVos = new ArrayList<>();

            if (CollectionUtil.isNotEmpty(items)) {
                for (Movement movement : items) {//遍历集合
                    Long movementUserId = movement.getUserId();//发布动态这个人的id
                    UserInfo userInfo = userInfoService.findById(movementUserId);//查询个人的信息

                    //3.将动态和个人的信息封装到一个新的vo对象
                    MovementVo movementVo = new MovementVo();
                    //数据的转换 个人-> vo
                    BeanUtil.copyProperties(userInfo, movementVo);
                    movementVo.setUserId(userInfo.getId());//赋值id信息
                    if (userInfo.getTags() != null) {//赋值标签信息
                        movementVo.setTags(userInfo.getTags().split(","));
                    }
                    //数据的转换 动态-> vo
                    BeanUtil.copyProperties(movement, movementVo);
                    //图片需要处理
                    if (CollectionUtil.isNotEmpty(movement.getMedias())) {
                        //将集合转成数组
                        movementVo.setImageContent(movement.getMedias().toArray(new String[]{}));
                    }
                    //距离写死
                    movementVo.setDistance("5公里");
                    //发布时间
                    String formatDate = DateFormatUtil.format(new Date(movement.getCreated()));
                    movementVo.setCreateDate(formatDate);
                    //将封装好的数据   给到集合
                    movementVos.add(movementVo);
                }
        }

        //4.将数据返回
        pageBeanVo.setItems(movementVos);
        System.out.println("----manager"+pageBeanVo);
        return pageBeanVo;
    }
*/


    /**
     *查询推荐的动态
     */
    public PageBeanVo findRecommendMovement(Integer pageNumber, Integer pageSize) {
        //1.获取登录用户的id
        Long userId = UserHolder.getId();
        //2.根据id调用service查询动态
        PageBeanVo pageBeanVo = movementService.findRecommendMovement(userId, pageNumber, pageSize);

        //3.组装返回数据
        List<Movement> items = (List<Movement>) pageBeanVo.getItems();
        //定义返回的数据集合
        List<MovementVo> movementVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(items)) {
            for (Movement movement : items) {
                //1.查询到动态发布人的而用户信息
                UserInfo userInfo = userInfoService.findById(movement.getUserId());
                //2.创建一个movementVo
                MovementVo movementVo = new MovementVo();
                //3.填充movementVo个人信息部分
                movementVo.setUserInfo(userInfo);
                //4.填充movementVo动态信息
                movementVo.setMovement(movement);
                //判断    该动态是否被点过赞   xx对哪个动态进行了点赞    缓存是否有这条数据
                String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movement.getId());
                String key3 = StrUtil.format(ConstantUtil.MOVEMENT_LOVE , UserHolder.getId(),movement.getId());
                if (stringRedisTemplate.hasKey(key)) {
                    movementVo.setHasLiked(1);//1表示已经点过赞
                }
                if (stringRedisTemplate.hasKey(key3)) {
                    movementVo.setHasLoved(1);//1表示已经喜欢
                }
                //5.将封装好的数据 添加到集合
                movementVoList.add(movementVo);
            }
        }
        pageBeanVo.setItems(movementVoList);
        return pageBeanVo;
    }

    @Reference
    private CommentService commentService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MQMovementManager mqMovementManager;

    //点赞
    public Integer saveMovementLike(String movementId) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(1);//点赞
        comment.setUserId(UserHolder.getId());//当前登录用户的id 操作人
        //2.保存对象
        Integer count = commentService.saveMovementComment(comment);
        //4.将数据存入缓存redis中   xx对哪个动态进行了点赞 userId，动态的id    "movement_like:用户id_动态id"
        //stringRedisTemplate.opsForValue().set(  "movement_like:"+userId+"_"+动态id+"", "1");   "movement_like:{}_{}";
        //StrUtil.format 工具类 作用: 将参数直接封装到字符串中 好处在于不需要拼接字符串 {} 表示占位符
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(),movementId);
        stringRedisTemplate.opsForValue().set(key, "1");

        //3.返回数据
        //发送MQ数据
        mqMovementManager.sendMessage(movementId, MQMovementManager.MOVEMENT_LIKE);
        return count;

    }
    //取消点赞
    public Integer deleteMovementLike(String movementId) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//动态id
        comment.setCommentType(1);//点赞
        comment.setUserId(UserHolder.getId());//当前登录用户的id 操作人
        //2.保存对象
        Integer count = commentService.deleteMovementComment(comment);
        //4.将数据从缓存中移除
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), movementId);
        stringRedisTemplate.delete(key);
        //3.返回数据
        //发送MQ操作
        mqMovementManager.sendMessage(movementId, MQMovementManager.MOVEMENT_DISLIKE);
        return count;
    }

    //动态喜欢
    public Integer saveMovementLove(String movementId) {
        //1.组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//当前登录用户id 操作人
        comment.setCommentType(3);//喜欢
        comment.setUserId(UserHolder.getId());
        //2.保存对象
        Integer count = commentService.saveMovementComment(comment);
        //3.将数据存入redis中
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LOVE , UserHolder.getId() , movementId);
        stringRedisTemplate.opsForValue().set(key, "3");
        //4.返回数据
        //发送MQ操作
        mqMovementManager.sendMessage(movementId, MQMovementManager.MOVEMENT_LOVE);
        return count;
    }
    //动态取消喜欢
    public Integer deleteMovementLove(String movementId) {
        //1.组装comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));//当前登录用户id 操作人
        comment.setCommentType(3);//喜欢
        comment.setUserId(UserHolder.getId());
        //2.保存对象
        Integer count = commentService.deleteMovementComment(comment);
        //3.将数据存入redis中
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LOVE , UserHolder.getId() , movementId);
        stringRedisTemplate.delete(key);
        //4.返回数据
        //发送MQ操作
        mqMovementManager.sendMessage(movementId, MQMovementManager.MOVEMENT_DISLOVE);
        return count;
    }

    /**
     * 单条动态
     * @param movementId
     * @return
     */
    public MovementVo findMovementById(String movementId) {
        //1.根据id查询动态对象
        Movement movement = movementService.findMovementById(movementId);
        //2.根据movement  查询用户信息
        UserInfo userInfo = userInfoService.findById(movement.getUserId());
        //3.创建对象
        MovementVo vo = new MovementVo();
        //4.赋值数据
        vo.setUserInfo(userInfo);
        vo.setMovement(movement);
        //发送MQ操作
        mqMovementManager.sendMessage(movementId, MQMovementManager.MOVEMENT_BROWSE);
        return vo;
    }

    /**
     *  查询动态的评论
     * @param pageNumber
     * @param pageSize
     * @param movementId
     * @return
     */
    public PageBeanVo findMovementComment(Integer pageNumber, Integer pageSize, String movementId) {
        //1.分页查询动态评论
        PageBeanVo pageBeanVo = commentService.findMovementComment(pageNumber, pageSize, movementId);

        //2.根据动态的评论查询个人信息
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();
        List<CommentVo> commentVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(items)) {
            for (Comment comment : items) {
                //3.封装CommentVo ->这是一个集合
                //查询个人信息
                UserInfo userInfo = userInfoService.findById(comment.getUserId());
                //创建对象
                CommentVo vo = new CommentVo();
                BeanUtil.copyProperties(userInfo, vo);
                BeanUtil.copyProperties(comment, vo);
                //处理时间字段
                vo.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(comment.getCreated()));
                //存入集合
                String key = StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, UserHolder.getId(),comment.getId());
                Boolean hasKey = stringRedisTemplate.hasKey(key);
                if (hasKey){
                    vo.setHasLiked(1);
                }
                commentVoList.add(vo);
            }
        }
        pageBeanVo.setItems(commentVoList);
        return pageBeanVo;
    }

    /**
     * 保存评论
     * @param movementId
     * @param content
     * @return
     */
    public Map saveMovementComment(String movementId, String content) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setCommentType(2);//评论
        comment.setUserId(UserHolder.getId());//操作人
        comment.setContent(content);//赋值评论内容
        comment.setPublishId(new ObjectId(movementId));//赋值动态id
        //2.直接保存即可
        commentService.saveMovementComment(comment);
        //发送MQ操作
        mqMovementManager.sendMessage(movementId, MQMovementManager.MOVEMENT_COMMENT);
        return null;
    }

    /**
     * 根据传入的类型  查询统计 喜欢 评论 点赞 列表
     * @param pageNumber
     * @param pageSize
     * @param commentType
     * @return
     */
    public PageBeanVo findCommentByCommentType(Integer pageNumber, Integer pageSize, int commentType) {
        //1.根据传入的类型 查询统计 喜欢 评论 点赞 列表
        PageBeanVo pageBeanVo = commentService.findCommentByCommentType(pageNumber, pageSize, commentType, UserHolder.getId());

        List<Comment> items = (List<Comment>) pageBeanVo.getItems();
        List<UserCommentVo> list = new ArrayList<>();
        //3.构造返回的vo
        if (CollectionUtil.isNotEmpty(items)) {
            for (Comment comment : items) {
                //根据评论查询用户的数据
                UserInfo userInfo = userInfoService.findById(comment.getUserId());
                //创建对象
                UserCommentVo vo = new UserCommentVo();
                vo.setNickname(userInfo.getNickname());//昵称
                vo.setAvatar(userInfo.getAvatar());//头像
                vo.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(comment.getCreated())));
                vo.setId(comment.getId().toHexString());//给评论的id
                //添加到集合
                list.add(vo);
            }
        }
        pageBeanVo.setItems(list);
        //2.返回数据
        return pageBeanVo;
    }

    @Reference
    private AnnouncementService announcementService;
    /**
     * 公告信息查询
     */
    public PageBeanVo findAnnouncements(Integer pageNumber, Integer pageSize) {
        //调用进行分页查询
        return announcementService.findAnnouncements(pageNumber, pageSize);
    }

    /**
     * 动态评论点赞
     * @param commentId
     * @return
     */
    public Integer movementCommentLike(String commentId) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(commentId));
        comment.setCommentType(6);//点赞
        comment.setUserId(UserHolder.getId());//当前登录用户的id 操作人
        //2.保存对象
        Integer count = commentService.movementCommentLike(comment);
        //4.将数据存入缓存redis中   xx对哪个动态进行了点赞 userId，动态的id    "movement_like:用户id_动态id"
        //stringRedisTemplate.opsForValue().set(  "movement_like:"+userId+"_"+动态id+"", "1");   "movement_like:{}_{}";
        //StrUtil.format 工具类 作用: 将参数直接封装到字符串中 好处在于不需要拼接字符串 {} 表示占位符
        String key = StrUtil.format(ConstantUtil.MOVEMENT_COMMENT_LIKE, UserHolder.getId(),commentId);
        stringRedisTemplate.opsForValue().set(key, "1");
        return count;
    }


    /**
     * 取消动态评论点赞
     * @param commentId
     * @return
     */
    public Integer deleteMovementCommentLike(String commentId) {
        //1.构建comment对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(commentId));//动态id
        comment.setCommentType(6);//点赞
        comment.setUserId(UserHolder.getId());//当前登录用户的id 操作人
        //2.保存对象
        Integer count = commentService.deleteMovementCommentLike(comment);
        //4.将数据从缓存中移除
        String key = StrUtil.format(ConstantUtil.MOVEMENT_LIKE, UserHolder.getId(), commentId);
        stringRedisTemplate.delete(key);

        return count;
    }
}
